package com.cskaoyan.javase.oop3._4anonymous._0introduction;

/**
 * 匿名内部类是特殊的局部内部类,它仍然定义在方法等局部位置,也仅在作用域内部生效
 *      它的成员特点,使用特点,访问特点等都和局部内部类类似
 *      补充: 匿名内部类没有构造器,因为类名都不知道,构造器根本就没用,也写不出来.
 *
 * 匿名内部类,指的是一个匿名的局部内部类,大家思考在之前,我们定义局部内部类时,
 *      往往都是为了得到类或者接口的子类对象
 *      这时,这个子类叫什么实际上是不重要的,重点是需要得到子类对象
 *      于是就出现类匿名内部类,也叫匿名内部类对象
 *
 * 语法:
 *      new 类名/接口名(){
 *          // 上面类或者接口的子类的类体
 *      }
 *      解释:
 *      1.new关键字表示创建对象,所以该匿名内部类语法,整体表示一个对象,而不是一个类
 *      2.整个语法表示的对象,是语法中写的类名/接口名的子类对象
 *          所以匿名内部类的语法中,隐含了继承或者实现
 *      3.整个语法表示创建子类对象,但是这个子类我们不知道它叫什么,所以这个语法叫匿名(子类的)内部类(对象)
 *      4.类名可以是普通类,也可以是抽象类
 *
 *
 * 匿名内部类对象的使用:
 *      new 类名/接口名(){
 *          // 上面类或者接口的子类的类体
 *      }
 *      以上语法整体表示一个对象
 *      并且实际上这个对象没有引用指向它,这是一个匿名对象,所以它就有两种使用方式
 *      1.可以用引用接收,这时就不是匿名对象了.
 *          必须,也只能用父类引用接收
 *          接收完毕后,就可以使用引用操作对象
 *          优点: 这时对象有引用指向,可以多用几次
 *          缺点: 无法访问子类独有成员,而且是真的无法访问,不能强转,因为不知道子类叫什么
 *              接收就多一步代码,会稍微麻烦一点.
 *
 *      2.可以直接调方法,访问成员.
 *          优点:
 *              不接收更快,更简洁,方便省事
 *              可以访问子类独有成员
 *          缺点:
 *              一次性的,无法多次使用
 *
 * 综上,使用匿名内部类对象时,可以根据具体的情况,具体决定.
 *
 * 小细节:
 *      匿名内部类语法中的小括号有用吗?
 *  对于类的匿名内部类对象,是有用的,可以用来调用父类的构造器.
 *  但是对于接口没有用.
 *
 * @since 15:42
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 匿名内部类是特殊的局部内部类,所以仍然在局部位置使用
        // 使用匿名内部类创建A类的子类对象
        A a = new A() {
            /*
                这是A类的子类类体
                可以重写父类方法
                也可以新增自身的成员
              */
            @Override
            public void testB() {
                System.out.println("我是匿名子类!");
            }
        };
        a.testB();
        a.testB();
        a.testB();

        AbstractA aa = new AbstractA() {
            int num = 10;
            @Override
            public void testA() {
                System.out.println("我是抽象类的匿名子类对象!");
            }
        };
        // System.out.println(aa.num);

        new IA(){
            int num = 100;
            @Override
            public void testC() {
                System.out.println("我是接口的匿名子类对象!");
            }
        }.testC();

        System.out.println(new IA() {
            int num = 100;
            @Override
            public void testC() {
                System.out.println("我是接口的匿名子类对象!");
            }
        }.num);

        // 调用父类的有参构造来创建匿名子类对象
        System.out.println(new AbstractA(888) {
            @Override
            public void testA() {
                System.out.println(a);
            }

        }.age);

    }
}

abstract class AbstractA {
    int age;

    public AbstractA(int age) {
        this.age = age;
    }

    public AbstractA() {
    }

    public abstract void testA();
}

class A {
    public void testB() {
        System.out.println("普通类中的方法");
    }
}

interface IA {
    void testC();
}